#include "event_loop.h"
#include <iostream>
#include <unordered_map>
#include <vector>
#include <set>

EventLoop::EventLoop(int thread_num) : _next_idx(0), _thread_num(thread_num){
    std::cout << "construt event_loop num is " << thread_num << std::endl;
    _work_threads.reserve(thread_num);
    for(int i = 0; i < thread_num; i++){
        // 1) 创建一个新的 IOThread
        auto thr = std::make_shared<IOThread>(i);
        // 2) 启动它
        thr->start();
        // 3) 再把它放进容器
        _work_threads.push_back(thr);
        // 初始连接数为 0
        _min_heap.push({0, (size_t)i});
    }
}

EventLoop::~EventLoop()
{
    for (int i = 0; i < _thread_num; ++i)
    {
        _work_threads[i]->join();
    }

    std::cout <<  "EventLoop exit" << std::endl;
}

void EventLoop::StopIOThread(){
    for (int i = 0; i < _thread_num; ++i)
    {
        _work_threads[i]->stop();
    }
}

std::shared_ptr<IOThread> EventLoop::get_idle_thread(size_t &out_index){
    //用最小堆实现
    std::lock_guard<std::mutex> lock(_heap_mtx);
    if(_min_heap.empty()) return nullptr;
    ThreadLoad tl = _min_heap.top();
    _min_heap.top();
    if (tl.index >= _work_threads.size() || !_work_threads[tl.index]) {
    out_index = -1;
        return nullptr;
    }
    out_index = tl.index;
    return _work_threads[tl.index];
    // //这里用 size_t 无符号整型的溢出性质来表示最大值
    // size_t min_conn_num = -1;
    // IOThread* idle_thread = nullptr;
    // for(auto& thread : _work_threads){
    //     if(thread->get_conn_num() < min_conn_num){
    //         min_conn_num = thread->get_conn_num();
    //         idle_thread = thread.get();
    //     }
    // }
    // return idle_thread;
}

void EventLoop::update_thread_load(size_t index, size_t conn_num) {
    std::lock_guard<std::mutex> lock(_heap_mtx);
    _min_heap.push({conn_num, index});
}

void EventLoop::NotifyNewCons(std::vector<int> &conns){
    std::set<size_t>notify_threads;
    for(int fd : conns){
        size_t idx;
        std::shared_ptr<IOThread> idle_thread = get_idle_thread(idx);
        if (!idle_thread) continue;

        idle_thread->catche_new_con(fd);

        // 更新负载
        size_t new_conn_num = idle_thread->get_conn_num() + 1; 
        update_thread_load(idx, new_conn_num);

        notify_threads.insert(idx);
        // auto index = fd % _work_threads.size();
        // _work_threads[index]->catche_new_con(fd);
        // notify_threads.insert(index);

        // IOThread* idle_thread = get_idle_thread();
        // if(idle_thread){
        //     idle_thread->catche_new_con(fd);
        //     for(size_t j = 0; j < _work_threads.size(); j++){
        //         if(_work_threads[j].get() == idle_thread){
        //             notify_threads.insert(j);
        //             break;
        //         }
        //     }
        // }
    }
    for(auto index: notify_threads){
        _work_threads[index]->wakeup();
    }
}